﻿Imports System.Net

Partial Public Class REST
    Public Sub New(ByVal Application As lfm.Application)
        Me.Application = Application
        Me.User = New User(Me.Application, Me)
        Me.mAuth = New Authorization(Application, Me)
    End Sub

End Class

Partial Public Class REST

    ''' <summary>
    ''' Http transfer method of a rest request.
    ''' </summary>
    ''' <remarks></remarks>
    Public Enum RestMethod
        ''' <summary>
        ''' Use http-get. Transfers rest data in query-string
        ''' </summary>
        HttpGet
        ''' <summary>
        ''' Use http-post. Tranfers rest data in request body with "application/x-www-form-urlencoded" encoding.
        ''' </summary>
        HttpPost
    End Enum

    ''' <summary>
    ''' The last.fm rest url.
    ''' </summary>
    Private RestUrl As String = "http://ws.audioscrobbler.com/2.0/"
    Public Property User As lfm.User
    Public Property UserSession As lfm.UserInfo
    Public Property Application As lfm.Application
    ''' <summary>
    ''' Executes a REST request to last.fm server.
    ''' </summary>
    ''' <param name="Method">API method to execute.</param>
    ''' <param name="Paramethers">Method paramethers.</param>
    ''' <param name="AppendSignature">Append Method Signature. In some methods this is required to be <code>true</code>.</param>
    ''' <param name="Authenticate">Use user cretantals to authenticate.</param>
    ''' <param name="HttpMethod">Http data transfer method.</param>
    ''' <returns>
    ''' An XDocument of answer.
    ''' </returns>
    ''' 
    Public Function ExecuteRest(ByVal Method As String, Optional ByVal Paramethers As SortedDictionary(Of String, String) = Nothing, Optional ByVal AppendSignature As Boolean = False, Optional ByVal Authenticate As Boolean = False, Optional ByVal HttpMethod As RestMethod = RestMethod.HttpGet) As XDocument
        Dim RequestUrl As String = RestUrl
        Dim RequestQuery As String = ""
        If Paramethers Is Nothing Then Paramethers = New SortedDictionary(Of String, String)
        Paramethers.Add("method", Method)
        Paramethers.Add("api_key", Me.Application.ApiKey)
        '' TODO: Authenticate
        For Each i In Paramethers
            RequestQuery += i.Key + "=" + System.Web.HttpUtility.UrlEncode(i.Value) + "&"
        Next i

        If AppendSignature Then
            RequestQuery += "api_sig=" + CreateSignature(Method, Paramethers)
        End If



        Dim Restresult As XDocument = Nothing

        Try
            If HttpMethod = RestMethod.HttpGet Then

                RequestUrl += "?" + RequestQuery
                Restresult = XDocument.Load(RequestUrl)

            ElseIf HttpMethod = RestMethod.HttpPost Then

                Dim restRequest As HttpWebRequest = HttpWebRequest.Create(RequestUrl)
                Dim content() As Byte = System.Text.UTF8Encoding.UTF8.GetBytes(RequestQuery)
                restRequest.ContentType = "application/x-www-form-urlencoded"
                restRequest.ContentLength = content.Length
                restRequest.GetRequestStream.Write(content, 0, content.Count)

                Dim restResponse As HttpWebResponse = restRequest.GetResponse

                Restresult = XDocument.Load(restResponse.GetResponseStream)

            End If
        Catch ex As WebException
#If DEBUG Then
            Message("ExecuteRest - " + ex.Status.ToString + " - " + ex.Message, ex.ToString)
#End If
            Restresult = XDocument.Parse("<lfm status=""error"">" + ex.Message + "</lfm>")
        End Try

#If DEBUG Then
            Message("ExecuteRest - Rest Result", Restresult.ToString())
#End If

            Return Restresult
    End Function

    ''' <summary>
    ''' Executes a REST request to last.fm server.
    ''' </summary>
    ''' <param name="Method">API method to execute.</param>
    ''' <param name="Paramethers">Method paramethers.</param>
    ''' <param name="AppendSignature">Append Method Signature. In some methods this is required to be <code>true</code>.</param>
    ''' <param name="Authenticate">Use user cretantals to authenticate.</param>
    ''' <returns>
    ''' An XDocument of answer.
    ''' </returns>
    Public Function ExecuteRest(ByVal Method As String, ByVal Paramethers As String(,), Optional ByVal AppendSignature As Boolean = False, Optional ByVal Authenticate As Boolean = False, Optional ByVal HttpMethod As RestMethod = RestMethod.HttpGet) As XDocument
        Dim Param As New SortedDictionary(Of String, String)
        For i = 0 To Paramethers.GetLength(0) - 1
            Param.Add(Paramethers(i, 0), Paramethers(i, 1))
        Next

        Return ExecuteRest(Method, Param, AppendSignature, Authenticate, HttpMethod)
    End Function

    ''' <summary>
    ''' Creates a method signature for last.fm rest queries
    ''' </summary>
    ''' <param name="Method">Method name.</param>
    ''' <param name="Paramethers">Paramethers</param>
    ''' <returns>Method signature.</returns>
    Private Function CreateSignature(ByVal Method As String, ByVal Paramethers As SortedDictionary(Of String, String)) As String
        If Not Paramethers.ContainsKey("api_key") Then Paramethers.Add("api_key", Me.Application.ApiKey)
        If Not Paramethers.ContainsKey("method") Then Paramethers.Add("method", Method)
        Dim Signature As String = ""
        For Each i In Paramethers
            Signature += i.Key + i.Value
        Next
        Signature += Me.Application.AppSecret

#If DEBUG Then
        Message("CreateSignature", Signature + vbCrLf + GenerateHashDigest(Signature, HashMethod.MD5))
#End If
        Return GenerateHashDigest(Signature, HashMethod.MD5)
    End Function
End Class
